
#ifndef MSTP_BRIDGE_DEF_H
#define MSTP_BRIDGE_DEF_H

#include "base_types.h"
#include "port.h"
#include "STP.h"

typedef const char* (*SM_GET_STATE_NAME) (SM_STATE state);
typedef SM_STATE (*SM_CHECK_CONDITIONS) (BRIDGE* bridge, int givenPort, int givenTree, SM_STATE state);
typedef void (*SM_INIT_STATE) (BRIDGE* bridge, int givenPort, int givenTree, SM_STATE state);

struct SM_INFO
{
	enum INSTANCE_TYPE
	{
		PER_BRIDGE,
		PER_BRIDGE_PER_TREE,
		PER_PORT,
		PER_PORT_PER_TREE,
	};

	INSTANCE_TYPE instanceType;

	const char* smName;

	SM_GET_STATE_NAME getStateName;
	SM_CHECK_CONDITIONS checkConditions;
	SM_INIT_STATE initState;
};

struct SM_INTERFACE
{
	const SM_INFO* smInfo;
	unsigned long smInfoCount;

	const SM_INFO* transmitSmInfo;
};

extern const SM_INTERFACE smInterface_802_1w_2001;
extern const SM_INTERFACE smInterface_802_1D_2004;
extern const SM_INTERFACE smInterface_802_1Q_2005;

// ============================================================================

// 13.23
struct BRIDGE_TREE
{
private:
	BRIDGE_ID				BridgeIdentifier;	// 13.23.2, 13.24.1 in 802.1Q-2011
	PRIORITY_VECTOR_SHORT	BridgePriority;		// 13.23.3, 13.24.2 in 802.1Q-2011

public:
	TIMES					BridgeTimes;		// 13.23.4, 13.24.3 in 802.1Q-2011
	unsigned short			rootPortId;			// 13.23.5
	PRIORITY_VECTOR_SHORT	rootPriority;		// 13.23.6
	TIMES					rootTimes;			// 13.23.7

private:
	void UpdateBridgePriorityFromBridgeIdentifier ()
	{
		int treeIndex = BridgeIdentifier.GetPriority () & 0x0FFF;
		if (treeIndex == CIST_INDEX)
		{
			BridgePriority.RootId = BridgeIdentifier;
			BridgePriority.ExternalRootPathCost = 0;
		}

		BridgePriority.RegionalRootId = BridgeIdentifier;
		BridgePriority.InternalRootPathCost = 0;
		BridgePriority.DesignatedBridgeId = BridgeIdentifier;
		BridgePriority.DesignatedPortId = 0;
	}

public:
	const BRIDGE_ID& GetBridgeIdentifier ()
	{
		return BridgeIdentifier;
	}

	void SetBridgeIdentifier (const BRIDGE_ID& newBridgeIdentifier)
	{
		BridgeIdentifier = newBridgeIdentifier;
		UpdateBridgePriorityFromBridgeIdentifier ();
	}

	void SetBridgeIdentifier (unsigned short settablePriorityComponent, unsigned short treeIndex, const unsigned char address[6])
	{
		BridgeIdentifier.Set (settablePriorityComponent, treeIndex, address);
		UpdateBridgePriorityFromBridgeIdentifier ();
	}

	const PRIORITY_VECTOR_SHORT& GetBridgePriority ()
	{
		return this->BridgePriority;
	}
};

// ============================================================================

// 13.23
struct BRIDGE
{
	char* logBuffer;
	unsigned long logBufferSize;
	unsigned long logBufferUsedSize;
	int logCurrentPort;
	int logCurrentTree;
	
	STP_MODE compatibilityMode;
	
	bool loggingEnabled;
	
	const STP_CALLBACKS* callbacks;

	bool BEGIN; // 13.23.1
	bool started;
	MST_CONFIG_ID MstConfigId; // 13.23.8	

	int portCount;
	int treeCount;

	BRIDGE_TREE** trees;
	PORT** ports;
	
	unsigned short ForceProtocolVersion;				// 13.22.e
	static const unsigned short MigrateTime = 3;		// 13.22.h --- 13.25.e --- 17.13.9 in 802.1D-2004 --- 17.20.9 in 802.1D-2004 ---
	static const unsigned short HelloTime = 2;
	static const unsigned short BridgeMaxAge = 20;		// 13.22.i --- 17.14 in 802.1D-2004
	static const unsigned short BridgeForwardDelay = 15;// 13.22.f --- 17.14 in 802.1D-2004
	static const unsigned short MaxHops = 20;			// 13.22.1 --- 13.23.7 --- 13.37.3
	static const unsigned long TransmitHoldCount = 6;	// 13.22.g --- 17.13.12 in 802.1D-2004
	
	SM_STATE* states;

	const SM_INTERFACE* smInterface;
	
	const MSTP_BPDU*		receivedBpduContent;
	VALIDATED_BPDU_TYPE		receivedBpduType;
};



#endif
